home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / dm3_src.zip / DMIO.C < prev    next >
C/C++ Source or Header  |  1990-08-02  |  90KB  |  2,430 lines

  1. /* ************************************************************************* */
  2. /*                                                                           */
  3. /*                 D O O R W A R E   I / O   L I B R A R Y                   */
  4. /*                                                                           */
  5. /*                            For Mycrosoft C                                */
  6. /*                                                                           */
  7. /* ************************************************************************* */
  8. /*                                                                           */
  9. /*      This module contains functions used to input and output info         */
  10. /*      with the user and  remote_users console.  Additionally, it           */
  11. /*      contains functions that interface with DOS.                          */
  12. /*                                                                           */
  13. /*      The following funtions are contained in this file:                   */
  14. /*                                                                           */
  15. /*              io_open         - Determine remote port number               */
  16. /*              io_reopen       - ReAquire comm port resources               */
  17. /*              io_close        - Release comm port resources                */
  18. /*                                                                           */
  19. /*              modem_carrier   - Test for carrier detect                    */
  20. /*              modem_status    - Test for remote char available             */
  21. /*              modem_input     - Read char from comm port                   */
  22. /*              modem_output    - Write char to comm port                    */
  23. /*              modem_wait      - Wait for output to complete                */
  24. /*              modem_iflush    - Flush input buffer                         */
  25. /*              modem_oflush    - Flush output buffer                        */
  26. /*                                                                           */
  27. /*              local_status    - Test for local char available              */
  28. /*              local_input     - Read char from keyboard                    */
  29. /*              local_cls       - Clear the local display                    */
  30. /*              local_output    - Write char to local display                */
  31. /*              local_print     - Write a string to local display            */
  32. /*              local_wait      - Wait for output to complete                */
  33. /*              local_iflush    - Flush input buffer                         */
  34. /*              local_oflush    - Flush output buffer                        */
  35. /*              get_local_cursor- Get the current local cursor position      */
  36. /*              set_local_cursor- Set the current local cursor position      */
  37. /*              set_local_banner- Set the banner                             */
  38. /*              put_local_banner- Write banner to display                    */
  39. /*                                                                           */
  40. /*              io_status       - Test for char available                    */
  41. /*              io_input        - Read char                                  */
  42. /*              io_linput       - Read line with line feed                   */
  43. /*              io_lxinput      - Read line without line feed                */
  44. /*              io_lexinput     - Read line without an echo                  */
  45. /*              tio_input       - Read char (timed)                          */
  46. /*              tio_linput      - Read line with line feed (timed)           */
  47. /*              tio_lxinput     - Read line without line feed (timed)        */
  48. /*              io_pause        - Wait for a carriage return                 */
  49. /*              io_output       - Write char                                 */
  50. /*              io_loutput      - Write line                                 */
  51. /*              io_wait         - Wait for output to complete                */
  52. /*              io_iflush       - Flush input buffer                         */
  53. /*              io_oflush       - Flush output buffer                        */
  54. /*                                                                           */
  55. /*              no_cursor       - Turn off local cursor                      */
  56. /*              small_cursor    - Set small local cursor                     */
  57. /*              medium_cursor   - Set medium local cursor                     */
  58. /*              large_cursor    - Set large local cursor                     */
  59. /*                                                                           */
  60. /*                                                                           */
  61. /* ************************************************************************* */
  62.  
  63.  
  64.  
  65. /* ************************************************************************* */
  66. /*                            PROGRAM HISTORY                                */
  67. /* ************************************************************************* */
  68. /* 06/20/87     Version 1.00                                                 */
  69. /* 01/01/90     Version 3.00                                                 */
  70. /*                                                                           */
  71. /*                                                                           */
  72. /*                                                                           */
  73. /* ************************************************************************* */
  74.  
  75.  
  76.  
  77. #include "dmcfg.h"                              /* Std. defines & includes   */
  78. #include "dmdata.h"                             /* Std DM storage            */
  79.  
  80.  
  81. /*
  82.  *
  83.  * Test environment control
  84.  *
  85.  * Set to 0 for standard version
  86.  * Set to 1 for test version
  87.  *
  88.  */
  89.  
  90. #define TEST_VERSION    0
  91.  
  92.  
  93. /*
  94.  *
  95.  * Structure definitions
  96.  *
  97.  */
  98.  
  99. struct          dmport_cfg
  100. {
  101.   int           defined;                /* Defined flags                     */
  102.                                         /*   0 = Not defined                 */
  103.                                         /*   1 = Default definition          */
  104.                                         /*   2 = Defined by config file      */
  105.   unsigned int  address;                /* Comm Port base address            */
  106.   unsigned int  irq_id;                 /* Interrupt request number          */
  107.   int           int_enable;             /* Interrupt enable flag             */
  108.                                         /*   0 = BIOS/Fossil I/O             */
  109.                                         /*   1 = Direct I/O                  */
  110.                                         /*   2 = Interrupt I/O               */
  111.   int           handshake;              /* Handshake flag                    */
  112.                                         /*   0 = No handshaking              */
  113.                                         /*   1 = XON/XOFF handshaking        */
  114.                                         /*   2 = RTS/CTS handshaking         */
  115.                                         /*   3 = Both 1 & 2                  */
  116.   int           passthru;               /* Passthrough flag                  */
  117.                                         /*   0 = No passthrough (Do RETI)    */
  118.                                         /*   1 = Pass int to original vector */
  119. };
  120.  
  121.  
  122. /*
  123.  *
  124.  * Local module storage
  125.  *
  126.  */
  127.  
  128. static  struct  dmport_cfg      dmio_ports[8] = /* I/O port definitions      */
  129.         { 1, 0x3f8, 4, 2, 2, 0,
  130.           1, 0x2f8, 3, 2, 2, 0,
  131.           1, 0x3e8, 4, 2, 2, 0,
  132.           1, 0x2e8, 3, 2, 2, 0,
  133.           0, 0x000, 0, 0, 0, 0,
  134.           0, 0x000, 0, 0, 0, 0,
  135.           0, 0x000, 0, 0, 0, 0,
  136.           0, 0x000, 0, 0, 0, 0 };
  137.  
  138. static  int     remote_port   = 0;
  139. static  int     io_init_state = 0;
  140. static  int     io_open_state = 0;
  141.  
  142. static  char    cls[5] = {"\033[2J"};
  143. static  char    eol[5] = {"\033[K"};
  144. static  long    mark_time;
  145. static  long    mark_time2;
  146. static  long    tick_time;
  147. static  int     chat_flag = 0;
  148. static  int     local_line_no = 24;
  149. static  char    banner_msg[81] = {"                                                                                "};
  150. static  char    banner_color;
  151.  
  152.  
  153. /******************************************************************************
  154.  *
  155.  * IO_OPEN - Open I/O channel(s)
  156.  *
  157.  * process      1. If no parameters, disable remote
  158.  *              2. Open node file
  159.  *              3. Read in port configurations if present
  160.  *              4. Initialize comm port i/o
  161.  *              5. Exit
  162.  * input        Node = -1 if no parameters
  163.  *              Else node = BBS node number
  164.  * output       Returns 0 if all ok
  165.  *              Returns -1 if can't open node file NODES.BBS
  166.  *              Returns -2 if illegal node number in NODES.BBS
  167.  *              Returns -3 if illegal port name in NODES.BBS
  168.  *              Returns -4 if illegal number of parameters in PORTS.BBS
  169.  *              Returns -5 if illegal comm port id in PORTS.BBS
  170.  *              Returns -6 if illegal comm port address in PORTS.BBS
  171.  *              Returns -7 if illegal IRQ number in PORTS.BBS
  172.  *              Returns -8 if illegal INT enable in PORTS.BBS
  173.  *              Returns -9 if illegal handshake in PORTS.BBS
  174.  *              Returns -10 if illegal passthrough in PORTS.BBS
  175.  *              Returns -11 if Duplicate comm port definition in PORTS.BBS
  176.  *              Returns -12 if No defined port ids in PORTS.BBS
  177.  *              Returns -13 if Port is not defined in PORTS.BBS
  178.  *****************************************************************************/
  179.  
  180. io_open(node)
  181. {
  182. #if COMPILER == MSC
  183. onexit_t        onexit();                       /* Onexit declaration        */
  184. #endif
  185. #if COMPILER == BTC
  186. int             atexit();
  187. #endif
  188.  
  189. void            io_close();
  190.  
  191. FS      rfd;                                    /* File descriptor           */
  192.  
  193. int     i, j, k;                                /* Work variables            */
  194. char    fname[80];                              /* File name                 */
  195.  
  196.    if(node == -1)                               /* If not remote...          */
  197.    {
  198.      remote_user = 0;                           /* ...then disable it        */
  199.      remote_port = 0;
  200.    }
  201.    else
  202.    {
  203.      bbs_node_info.snoop[1] = '1';              /* Force on temporarily      */
  204.  
  205.      strcpy(rfd.name, bbs_dir);                 /* Build filename            */
  206.      strcat(rfd.name, "NODES.BBS");             /* Open node file            */
  207.      i = file_open(&rfd, FREAD, FTEXT, FNOCREATE); /* Open node file         */
  208.      if(i)                                      /* If file not there...      */
  209.        return(-1);                              /* ...error                  */
  210.  
  211.      i = 0;                                     /* Set states                */
  212.      j = 1;
  213.      if(node == 0)
  214.        k = 1;
  215.      else
  216.        k = node;
  217.      while((i < k) & (j != 0))                  /* Do until at right rec...  */
  218.      {
  219.        if(fgets(dminbuff, 255, rfd.fd))         /* ...if all ok...           */
  220.          i++;                                   /* ......continue            */
  221.        else
  222.          j = 0;                                 /* ...else past eof          */
  223.      }
  224.      file_close(&rfd);                          /* Close the file            */
  225.      if(j == 0)                                 /* If at eof...              */
  226.        return(-2);                              /* ...error                  */
  227.  
  228.      i = 0;                                     /* Init index                */
  229.      while((dminbuff[i] != 0x0d) &&             /* Do until end of line...   */
  230.            (dminbuff[i] != 0x0a) &&
  231.            (dminbuff[i] != ' ') &&
  232.            (dminbuff[i] != 0x09) &&
  233.            (dminbuff[i] != 0x1a) &&
  234.            (dminbuff[i] != 0x00))
  235.      {
  236.        fname[i] = dminbuff[i];                  /* ...store the character    */
  237.        i++;                                     /* ...adjust index           */
  238.      }
  239.      fname[i] = '\0';                           /* Terminate the string      */
  240.      remote_user = atoi(&(fname[i - 1]));       /* Get comm port number      */
  241.      remote_port = remote_user;
  242.  
  243.      if(((remote_user == 0) && (strnicmp(fname, "COM0", 4) != 0)) ||
  244.         (strnicmp(fname, "COM", 3) != 0))
  245.        return(-3);                              /* Error if bad device       */
  246.  
  247.      if(remote_user)                            /* If remote active...       */
  248.      {
  249.        i = dmread_ports();                      /* ...then read port info    */
  250.        if(i)                                    /* ...If an error            */
  251.          return(i - 2);                         /* ......then return it      */
  252.        else
  253.        {
  254.          if(dmio_ports[remote_user - 1].defined == 0)
  255.            return(-13);
  256.  
  257.          dmcomm_init(remote_user - 1,
  258.                      dmio_ports[remote_user - 1].address,
  259.                      dmio_ports[remote_user - 1].irq_id,
  260.                      dmio_ports[remote_user - 1].int_enable,
  261.                      dmio_ports[remote_user - 1].handshake,
  262.                      dmio_ports[remote_user - 1].passthru);
  263.  
  264.          if(io_init_state == 0)
  265.          {
  266. #if COMPILER == MSC
  267.            onexit(io_close);
  268. #endif
  269. #if COMPILER == BTC
  270.            atexit(io_close);
  271. #endif
  272.            io_init_state = 1;
  273.          }
  274.          io_open_state = 1;
  275.        }
  276.      }
  277.    }
  278.    return(0);                                   /* ...all is ok              */
  279. }
  280.  
  281.  
  282. /******************************************************************************
  283.  *
  284.  * IO_REOPEN - ReOpen I/O channel(s)
  285.  *
  286.  * process      1. If no parameters, disable remote
  287.  *              2. Initialize comm port i/o
  288.  *              3. Exit
  289.  * input        Node = -1 if no parameters
  290.  *              Else node = BBS node number
  291.  * output       Returns 0 if all ok
  292.  *****************************************************************************/
  293.  
  294. io_reopen()
  295. {
  296.    remote_user = remote_port;
  297.    if(remote_user)                              /* If remote only...         */
  298.    {
  299.      if(io_open_state == 0)
  300.      {
  301.        dmcomm_init(remote_user - 1,
  302.                    dmio_ports[remote_user - 1].address,
  303.                    dmio_ports[remote_user - 1].irq_id,
  304.                    dmio_ports[remote_user - 1].int_enable,
  305.                    dmio_ports[remote_user - 1].handshake,
  306.                    dmio_ports[remote_user - 1].passthru);
  307.  
  308.        io_open_state = 1;
  309.      }
  310.    }
  311.    return(0);                                   /* ...all is ok              */
  312. }
  313.  
  314.  
  315. /******************************************************************************
  316.  *
  317.  * IO_CLOSE - Release I/O resources
  318.  *
  319.  * process      1. If local, exit
  320.  *              2. Release resources
  321.  *              3. Exit
  322.  * input        None
  323.  * output       Returns AX = 0
  324.  *****************************************************************************/
  325.  
  326. void    io_close()
  327. {
  328.    /*
  329.     * Release if in use
  330.     */
  331.  
  332.     if(io_open_state)
  333.     {
  334.       dmcomm_wait();                            /* ...ten wait for i/o done  */
  335.       dmcomm_release();                         /* ...and release resources  */
  336.     }
  337.     io_open_state = 0;
  338.     remote_user = 0;
  339.  
  340.     return;                                     /* Always return 0           */
  341. }
  342.  
  343.  
  344. /******************************************************************************
  345.  *
  346.  * MODEM_CARRIER - Test for carrier detect
  347.  *
  348.  * process      1. Pretend all ok if remote is not active
  349.  *              2. Test modem status via BIOS
  350.  *              3. Return status info
  351.  * input        Uses remote user data values
  352.  * output       Returns 0 if remote_user is inactive
  353.  *              Returns 0 if carrier is still active
  354.  *              Returns 1 if carrier dropped
  355.  *****************************************************************************/
  356.  
  357. modem_carrier()
  358. {
  359.    #if TEST_VERSION
  360.    return(0);                                   /* always return 0 if test   */
  361.    #endif
  362.  
  363.    if(remote_user == 0)                         /* If line not in use...     */
  364.      return(0);                                 /* ...pretend all is ok      */
  365.  
  366.    if((dmcomm_regs() & 0x80) != 0)              /* Test carrier detect       */
  367.      return(0);                                 /* All ok here               */
  368.    else
  369.      return(1);                                 /* Ooops, lost carrier       */
  370. }
  371.  
  372.  
  373. /******************************************************************************
  374.  *
  375.  * MODEM_STATUS - Test for remote char available
  376.  *
  377.  * process      1. Return no data if remote is not active
  378.  *              2. Read status infor from BIOS
  379.  *              3. Return input status
  380.  * input        Uses remote user data values
  381.  * output       Returns 0 if remote user is inactive
  382.  *              Returns 0 if no remote char present
  383.  *              Returns 2 if remote char is available
  384.  *****************************************************************************/
  385.  
  386. modem_status()
  387. {
  388.    #if TEST_VERSION
  389.    return(0);                                   /* always return 0 if test   */
  390.    #endif
  391.  
  392.    if(remote_user == 0)                         /* If line not in use...     */
  393.      return(0);                                 /* ...then no key pressed    */
  394.  
  395.    if(dmcomm_status() == 1)                     /* Test key pressed          */
  396.      return(2);                                 /* ... key pressed           */
  397.    else
  398.      return(0);                                 /* ... no key                */
  399. }
  400.  
  401.  
  402. /******************************************************************************
  403.  *
  404.  * MODEM_INPUT - Read a remote chararcter
  405.  *
  406.  * process      1. Read data via BIOS
  407.  *              2. Mask it to ASCII
  408.  *              3. Return data
  409.  * input        Uses remote user data values
  410.  * output       Returns 0 if remote_user is inactive
  411.  *              Returns character
  412.  *****************************************************************************/
  413.  
  414. modem_input()
  415. {
  416. int     c;
  417.  
  418.    #if TEST_VERSION
  419.    return(0);                                   /* always return 0 if test   */
  420.    #endif
  421.  
  422.   c = dmcomm_input();                           /* Execute                   */
  423.   if(c == -1)                                   /* ...if loss of carrier     */
  424.     return(0);                                  /* ...then return null       */
  425.  
  426.   return(c & 0x7f);                             /* Return data               */
  427. }
  428.  
  429. /******************************************************************************
  430.  *
  431.  * MODEM_OUTPUT - Write a remote character
  432.  *
  433.  * process      1. Ignore if remote inactive
  434.  *              2. Write remote data via BIOS
  435.  *              3. Test if line feed
  436.  *              4. Return no error if not
  437.  *              5. Output nulls
  438.  *              6. Return no error
  439.  * input        Uses remote user data values
  440.  *              Data to output
  441.  * output       Returns 0
  442.  *****************************************************************************/
  443.  
  444. modem_output(data)
  445.  
  446. int     data;                                   /* Data to output            */
  447. {
  448. int     i;                                      /* Work variable             */
  449.  
  450.    #if TEST_VERSION
  451.    return(0);                                   /* no output if test version */
  452.    #endif
  453.  
  454.    if(remote_user)                              /* Only if remote active...  */
  455.    {
  456.      if(modem_carrier())                        /* Ignore if no carrier      */
  457.        return(-1);
  458.  
  459.      dmcomm_output(data);                       /* Execute                   */
  460.  
  461.      if(data == '\n')                           /* If it is a line feed...   */
  462.      {
  463.        for(i = 0 ; i < user_nulls ; i++)        /* ... send his nulls        */
  464.          dmcomm_output(0);
  465.      }
  466.    }
  467.    return(0);                                   /* No errors                 */
  468. }
  469.  
  470.  
  471. /******************************************************************************
  472.  *
  473.  * MODEM_WAIT - Wait for modem output to complete
  474.  *
  475.  * process      1. If local, exit
  476.  *              2. Wait for TX buffer empty
  477.  *              3. Exit
  478.  * input        None
  479.  * output       Returns AX = -1 if no carrier
  480.  *              Returns AX = 0 if TX buffer empty
  481.  *              Returns AX = 1 if timeout
  482.  *****************************************************************************/
  483.  
  484. modem_wait()
  485. {
  486.    /*
  487.     * Wait if in use
  488.     */
  489.  
  490.     if(remote_user)                             /* If remote active...       */
  491.       return(dmcomm_wait());                    /* ...then wait for complete */
  492. }
  493.  
  494.  
  495. /******************************************************************************
  496.  *
  497.  * MODEM_IFLUSH - Purge all input
  498.  *
  499.  * process      1. If local, exit
  500.  *              2. Clear the buffers
  501.  *              3. Exit
  502.  * input        None
  503.  * output       Returns AX = 0
  504.  *****************************************************************************/
  505.  
  506. modem_iflush()
  507. {
  508.    /*
  509.     * Flush buffers if in use
  510.     */
  511.  
  512.     if(remote_user)                             /* If remote active...       */
  513.       dmcomm_iflush();                          /* ...then flush input       */
  514.  
  515.     return(0);                                  /* Always returns 0          */
  516. }
  517.  
  518.  
  519. /******************************************************************************
  520.  *
  521.  * MODEM_OFLUSH - Purge all output
  522.  *
  523.  * process      1. If local, exit
  524.  *              2. Clear the buffers
  525.  *              3. Exit
  526.  * input        None
  527.  * output       Returns AX = 0
  528.  *****************************************************************************/
  529.  
  530. modem_oflush()
  531. {
  532.    /*
  533.     * Flush buffers if in use
  534.     */
  535.  
  536.     if(remote_user)                             /* If remote active...       */
  537.       dmcomm_oflush();                          /* ...then flush input       */
  538.  
  539.     return(0);                                  /* Always returns 0          */
  540. }
  541.  
  542.  
  543. /******************************************************************************
  544.  *
  545.  * LOCAL_STATUS - Test for local char available
  546.  *
  547.  * process      1. Read the status
  548.  *              2. Return input status
  549.  * input        none
  550.  * output       Returns 0 if no local char present
  551.  *              Returns 1 if local char is available
  552.  *****************************************************************************/
  553.  
  554. local_status()
  555. {
  556.    if(kbhit())                                  /* Test local status         */
  557.      return(1);                                 /* Local data available      */
  558.    else
  559.      return(0);                                 /* No local data available   */
  560. }
  561.  
  562.  
  563. /******************************************************************************
  564.  *
  565.  * LOCAL_INPUT - Read a local chararcter
  566.  *
  567.  * process      1. Read data via BIOS
  568.  *              2. Mask it to ASCII
  569.  *              3. Return data
  570.  * input        Uses remote user data values
  571.  * output       Returns character
  572.  *****************************************************************************/
  573.  
  574. local_input()
  575. {
  576. long    cur_time();                             /* Get current time          */
  577. union   REGS inregs, outregs;                   /* BIOS access structures    */
  578. struct  SREGS   segregs;
  579. long    time_val;                               /* Current time value        */
  580. int     key;                                    /* Keyboard character        */
  581. char    msg[32];                                /* Work buffer               */
  582.  
  583.    inregs.x.ax = (0x0000);                      /* Function number           */
  584.    int86x(0x16, &inregs, &outregs, &segregs);   /* Execute                   */
  585.    key = outregs.x.ax;                          /* Set to ASCII data         */
  586.  
  587.  
  588.    /* Test for SysOp Keys */
  589.  
  590.    if(remote_user)
  591.    {
  592.      /* Test for ANY toggle */
  593.  
  594.      if(key == 0x3e00)
  595.      {
  596.        if(bbs_node_info.sysop_annoy[1] == '1')
  597.        {
  598.          local_print("\r\nSysOp annoy disabled...\r\n");
  599.          bbs_node_info.sysop_annoy[1] = '0';
  600.        }
  601.        else
  602.        {
  603.          local_print("\r\nSysOp annoy enabled...\r\n");
  604.          bbs_node_info.sysop_annoy[1] = '1';
  605.        }
  606.        return(0);                               /* Exit NULL character       */
  607.      }
  608.  
  609.  
  610.      /* Test for AVL toggle */
  611.  
  612.      if(key == 0x4000)
  613.      {
  614.        if(bbs_node_info.sysop_avail[1] == '1')
  615.        {
  616.          local_print("\r\nSysOp avail disabled...\r\n");
  617.          bbs_node_info.sysop_avail[1] = '0';
  618.        }
  619.        else
  620.        {
  621.          local_print("\r\nSysOp avail enabled...\r\n");
  622.          bbs_node_info.sysop_avail[1] = '1';
  623.        }
  624.        return(0);                               /* Exit NULL character       */
  625.      }
  626.  
  627.  
  628.      /* Test for Snoop toggle */
  629.  
  630.      if(key == 0x4300)
  631.      {
  632.        if(bbs_node_info.snoop[1] == '1')
  633.        {
  634.          local_print("\r\nSysOp snoop disabled...\r\n");
  635.          local_cls();
  636.          no_cursor();
  637.          bbs_node_info.snoop[1] = '0';
  638.        }
  639.        else
  640.        {
  641.          local_print("\r\nSysOp snoop enabled...\r\n");
  642.          put_local_banner();
  643.          small_cursor();
  644.          bbs_node_info.snoop[1] = '1';
  645.        }
  646.        return(0);                               /* Exit NULL character       */
  647.      }
  648.  
  649.  
  650.      /* Test for Controls */
  651.  
  652.      if(key == 0x6800)
  653.      {
  654.        local_print("\rUser aborted...\r\n");
  655.        user_signoff = cur_time();
  656.        key          = 0;
  657.      }
  658.      else if(key == 0x4d00)
  659.      {
  660.        user_signoff += 60L;
  661.        time_val      = cur_time();
  662.        if(time_val < user_signon)
  663.          time_val   += DAY_SECONDS;
  664.        sprintf(msg, "\rUser time = %ld [%ld].\r\n", (user_signoff - time_val) / 60L, (user_signoff - user_signon) / 60L);
  665.        local_print(msg);
  666.        key          = 0;
  667.      }
  668.      else if(key == 0x4b00)
  669.      {
  670.        user_signoff -= 60L;
  671.        sprintf(msg, "\rUser time = %ld...\r\n", (user_signoff - user_signon) / 60L);
  672.        local_print(msg);
  673.        key          = 0;
  674.      }
  675.  
  676.  
  677.      /* Test for CHAT */
  678.  
  679.      if((key == 0x4400) && (chat_flag == 0))
  680.      {
  681.        print_string("\r\nHi this is your SysOp. Sorry to break in and chat...\r\n");
  682.        chat_flag = 1;                           /* Set chat active           */
  683.        chat_mode();
  684.        chat_flag = 0;                           /* Set chat inactive         */
  685.        return(0);                               /* Exit NULL character       */
  686.      }
  687.  
  688.    }
  689.    return(key & 0x7f);                          /* Return character          */
  690. }
  691.  
  692.  
  693. /******************************************************************************
  694.  *
  695.  * LOCAL_CLS - Clear local dislay
  696.  *
  697.  * process      1. Send command to BIOS
  698.  *              2. Exit
  699.  * input        None
  700.  * output       None
  701.  *****************************************************************************/
  702.  
  703. local_cls()
  704. {
  705. union   REGS inregs, outregs;                   /* BIOS access structures    */
  706. struct  SREGS   segregs;
  707. int     key;                                    /* Keyboard character        */
  708.  
  709.    inregs.h.ah = (0x06);                        /* Function number to scroll */
  710.    inregs.h.al = (0x00);                        /* Set to clear display      */
  711.    inregs.h.bh = (0x07);                        /* Attribute for filler      */
  712.    inregs.h.bl = (0x00);                        /* Page to scroll            */
  713.    inregs.h.cl = (0x00);                        /* Top left of window        */
  714.    inregs.h.ch = (0x00);
  715.    inregs.h.dl = (0x4f);                        /* Bottom right of window    */
  716.    inregs.h.dh = (0x18);
  717.    int86x(0x10, &inregs, &outregs, &segregs);   /* Execute                   */
  718.    return(0);                                   /* Exit no errors            */
  719. }
  720.  
  721.  
  722. /******************************************************************************
  723.  *
  724.  * LOCAL_BELL - Beep local console
  725.  *
  726.  * process      1. Write the data
  727.  *              2. Exit no error
  728.  * input        None
  729.  * output       Returns 0
  730.  *****************************************************************************/
  731.  
  732. local_bell()
  733. {
  734.    putchar('\007');                             /* Send to local console     */
  735.    return(0);                                   /* Exit no errors            */
  736. }
  737.  
  738.  
  739. /******************************************************************************
  740.  *
  741.  * LOCAL_OUTPUT - Write a local character
  742.  *
  743.  * process      1. Write the data
  744.  *              2. Test for line feed
  745.  *              3. Exit no error if not
  746.  *              4. Test for past line 23
  747.  *              5. Exit no error if not
  748.  *              6. Scroll the screen
  749.  *              7. Get current cursor position
  750.  *              8. Back up one line
  751.  *              9. Set new cursor position
  752.  *             10. Exit no error
  753.  * input        Data to output
  754.  * output       Returns 0
  755.  *****************************************************************************/
  756.  
  757. local_output(data)
  758.  
  759. int     data;                                   /* Data to output            */
  760. {
  761. union   REGS inregs, outregs;                   /* BIOS access structures    */
  762. struct  SREGS   segregs;
  763. int     x, y;                                   /* Cursor position           */
  764.  
  765.    if((remote_user == 0) || (bbs_node_info.snoop[1] == '1'))
  766.    {
  767.      if((remote_user == 0) || (data != '\007'))
  768.        putchar(data);                           /* Send to local console     */
  769.      if(data == '\n')                           /* If going to a new line... */
  770.      {
  771.        local_line_no++;                         /* ...Bump line number       */
  772.        if(local_line_no > 23)                   /* ...If at bottom...        */
  773.        {
  774.          get_local_cursor(&x, &y);              /* Get current position      */
  775.  
  776.          inregs.h.ah = (0x06);                  /* Function number to scroll */
  777.          inregs.h.al = (0x01);                  /* Lines to scroll           */
  778.          inregs.h.bh = (0x07);                  /* Attribute for filler      */
  779.          inregs.h.bl = (0x00);                  /* Page to scroll            */
  780.          inregs.h.cl = (0x00);                  /* Top left of window        */
  781.          inregs.h.ch = (0x00);
  782.          inregs.h.dl = (0x4f);                  /* Bottom right of window    */
  783.          inregs.h.dh = (0x17);
  784.          int86x(0x10, &inregs, &outregs, &segregs);     /* Execute           */
  785.  
  786. /*       set_local_cursor(x, 23);       */      /* Set new position          */
  787.          set_local_cursor(0, 23);               /* Set new position          */
  788.  
  789.          local_line_no = 23;                    /* ......set it back         */
  790.        }
  791.      }
  792.    }
  793.    return(0);                                   /* Exit no errors            */
  794. }
  795.  
  796.  
  797. /******************************************************************************
  798.  *
  799.  * LOCAL_PRINT - Print string locally
  800.  *
  801.  * process      1. Print a char
  802.  *              2. Exit if done
  803.  *              3. Next char
  804.  *              4. Goto 1
  805.  * input        Pointer to string
  806.  * output       Returns 0
  807.  *****************************************************************************/
  808.  
  809.  
  810. local_print(string)
  811.  
  812. char    *string;                                /* String to print           */
  813. {
  814. int     i;
  815.  
  816.   for(i = 0 ; i < strlen(string) ; i++)
  817.     local_output(string[i]);
  818.  
  819.   return(0);
  820. }
  821.  
  822.  
  823. /******************************************************************************
  824.  *
  825.  * LOCAL_WAIT - Wait for output to complete (provided only for balance)
  826.  *
  827.  * process      1. Exit
  828.  * input        None
  829.  * output       Returns AX = 0
  830.  *****************************************************************************/
  831.  
  832. local_wait()
  833. {
  834.    /*
  835.     * Provided only for balance
  836.     */
  837.  
  838.     return(0);                                  /* Exit, nothing to do       */
  839. }
  840.  
  841.  
  842. /******************************************************************************
  843.  *
  844.  * LOCAL_IFLUSH - Purge all input
  845.  *
  846.  * process      1. If no chars then goto 3
  847.  *              2. Input char & goto 1
  848.  *              3. Exit
  849.  * input        None
  850.  * output       Returns AX = 0
  851.  *****************************************************************************/
  852.  
  853. local_iflush()
  854. {
  855. int     st;
  856.  
  857.    /*
  858.     * Flush all input
  859.     */
  860.  
  861.     st = 1;
  862.     while(st)                                   /* Do until nothing left     */
  863.     {
  864.       if(local_status())                        /* If chars available...     */
  865.         local_input();                          /* ...then flush input       */
  866.       else                                      /* Otherwise...              */
  867.         st = 0;                                 /* ...all done               */
  868.     }
  869.  
  870.     return(0);                                  /* Always returns 0          */
  871. }
  872.  
  873.  
  874. /******************************************************************************
  875.  *
  876.  * LOCAL_OFLUSH - Purge all output (Provided only for balance)
  877.  *
  878.  * process      1. Exit
  879.  * input        None
  880.  * output       Returns AX = 0
  881.  *****************************************************************************/
  882.  
  883. local_oflush()
  884. {
  885.    /*
  886.     * Provided only for balance
  887.     */
  888.  
  889.     return(0);                                  /* Always returns 0          */
  890. }
  891.  
  892.  
  893. /******************************************************************************
  894.  *
  895.  * GET_LOCAL_CURSOR - Get current local cursor position
  896.  *
  897.  * process      1. Make BIOS call
  898.  *              2. Return data
  899.  * input        Pointer to return parms
  900.  * output       Returns 0
  901.  *****************************************************************************/
  902.  
  903. get_local_cursor(xpos, ypos)
  904.  
  905. int     *xpos;                                  /* Pointer to x position     */
  906. int     *ypos;                                  /* Pointer to y position     */
  907. {
  908. union   REGS inregs, outregs;                   /* BIOS access structures    */
  909. struct  SREGS   segregs;
  910.  
  911.    inregs.x.ax = (0x0300);                      /* Function number           */
  912.    int86x(0x10, &inregs, &outregs, &segregs);   /* Execute                   */
  913.    *xpos = outregs.h.dl;                        /* Return the parms          */
  914.    *ypos = outregs.h.dh;
  915.    return(0);                                   /* Exit no errors            */
  916. }
  917.  
  918.  
  919. /******************************************************************************
  920.  *
  921.  * SET_LOCAL_CURSOR - Set current local cursor position
  922.  *
  923.  * process      1. Make BIOS call
  924.  *              2. Return
  925.  * input        X & Y positions
  926.  * output       Returns 0
  927.  *****************************************************************************/
  928.  
  929. set_local_cursor(xpos, ypos)
  930.  
  931. int     xpos;                                   /* x position                */
  932. int     ypos;                                   /* y position                */
  933. {
  934. union   REGS inregs, outregs;                   /* BIOS access structures    */
  935. struct  SREGS   segregs;
  936.  
  937.    inregs.x.ax = (0x0200);                      /* Function number           */
  938.    inregs.x.bx = (0x0000);                      /* Page number               */
  939.    inregs.h.dl = xpos;                          /* Position to go to         */
  940.    inregs.h.dh = ypos;
  941.    int86x(0x10, &inregs, &outregs, &segregs);   /* Execute                   */
  942.    return(0);                                   /* Exit no errors            */
  943. }
  944.  
  945.  
  946. /******************************************************************************
  947.  *
  948.  * SET_LOCAL_BANNER - Setup local banner line
  949.  *
  950.  * process      1. Store in local char array
  951.  *              2. Return
  952.  * input        Pointer to banner message
  953.  * output       Returns 0
  954.  *****************************************************************************/
  955.  
  956. set_local_banner(string, foreground, background)
  957.  
  958. char    *string;                                /* Banner message            */
  959. {
  960.    strcpy(banner_msg, string);                  /* Copy it over              */
  961.    banner_color = (background << 4) + foreground;
  962.    return(0);                                   /* Exit no errors            */
  963. }
  964.  
  965.  
  966. /******************************************************************************
  967.  *
  968.  * PUT_LOCAL_BANNER - Write local banner line to screen
  969.  *
  970.  * process      1. Save current cursor position
  971.  *              2. Set cursor to line 25
  972.  *              3. Write the banner
  973.  *              4. Reset cursor back to its position
  974.  *              5. Return no error
  975.  * input        None
  976.  * output       Returns 0
  977.  *****************************************************************************/
  978.  
  979. put_local_banner()
  980. {
  981. union   REGS inregs, outregs;                   /* BIOS access structures    */
  982. struct  SREGS   segregs;
  983. int     x, y;                                   /* Cursor position           */
  984. int     i;                                      /* Loop variable             */
  985.  
  986.    if((remote_user == 0) || (bbs_node_info.snoop[1] == '1'))
  987.    {
  988.      get_local_cursor(&x, &y);                  /* Save current location     */
  989.  
  990.      for(i = 0 ; i < 80 ; i++)                  /* Copy the line             */
  991.      {
  992.        set_local_cursor(i, 24);                 /* Set location to print     */
  993.        inregs.h.ah = (0x09);                    /* Function number           */
  994.        inregs.h.al = banner_msg[i];             /* Function number           */
  995.        inregs.h.bh = (0x00);                    /* Page number               */
  996.        inregs.h.bl = banner_color;              /* Color attributes          */
  997.        inregs.x.cx = (0x0001);                  /* Output count              */
  998.        int86x(0x10, &inregs, &outregs, &segregs);       /* Execute           */
  999.      }
  1000.      if(y > 23)                                 /* If we are too low...      */
  1001.        y = 23;                                  /* ...then backup            */
  1002.      set_local_cursor(x, y);                    /* Restore cursor position   */
  1003.    }
  1004.    return(0);                                   /* Exit no errors            */
  1005. }
  1006.  
  1007.  
  1008. /******************************************************************************
  1009.  *
  1010.  * IO_STATUS - Test for char available
  1011.  *
  1012.  * process      1. Test local status
  1013.  *              2. Return true if local ready
  1014.  *              3. Test remote status
  1015.  *              4. Return true if remote ready
  1016.  *              4. Return false
  1017.  * input        none
  1018.  * output       Returns 0 if no char present
  1019.  *              Returns 1 if local char is available
  1020.  *              Returns 2 if remote char is available
  1021.  *****************************************************************************/
  1022.  
  1023. io_status()
  1024. {
  1025.    if(local_status())                           /* Test local console        */
  1026.      return(1);                                 /* exit if key pressed       */
  1027.  
  1028.    if(modem_status())                           /* Test remote console       */
  1029.      return(2);                                 /* exit if key pressed       */
  1030.  
  1031.    return(0);                                   /* else no key               */
  1032. }
  1033.  
  1034.  
  1035. /******************************************************************************
  1036.  *
  1037.  * IO_TESTS - Test time & line controls
  1038.  *
  1039.  * process      1. Test carrier detect
  1040.  *              2. Return -1 if carrier dropped
  1041.  *              3. Test for no activity
  1042.  *              4. Return -2 if no activity
  1043.  *              5. Return -2 if no activity
  1044.  *              6. Test for time limit exceeded
  1045.  *              7. Return -3 if less than 2 minutes
  1046.  *              8. Return -4 if time limit exceeded
  1047.  *              9. Return 0 (all ok)
  1048.  * input        none
  1049.  * output       Returns -1 if carrier dropped
  1050.  *              Returns -2 if no remote activity
  1051.  *              Returns -3 if less than 2 minutes remaining
  1052.  *              Returns -4 if no time remaining
  1053.  *              Returns  0 if no errors
  1054.  *****************************************************************************/
  1055.  
  1056. io_tests()
  1057. {
  1058. long    cur_time();                             /* Get current time decl     */
  1059. long    check_time;                             /* Cur time storage          */
  1060. int     stat;                                   /* Input status variable     */
  1061.  
  1062.    mark_time = cur_time();                      /* Flag current time         */
  1063.  
  1064.    if(modem_carrier())                          /* If carrier dropped...     */
  1065.      return(-1);                                /* ...exit with error        */
  1066.  
  1067.    check_time = cur_time();                     /* Check current time        */
  1068.    if(check_time < mark_time)                   /* If we wrapped past 12...  */
  1069.      check_time += DAY_SECONDS;                 /* ...adjust it              */
  1070.    if(check_time > (mark_time + 180L))          /* If it has been 3 mins...  */
  1071.      return(-2);                                /* ...exit with error        */
  1072.  
  1073.    stat = test_timeout();                       /* Test remote time access   */
  1074.    if(stat == -1)                               /* If time warning msg...    */
  1075.      return(-3);                                /* ...exit with warning      */
  1076.    if(stat == -2)                               /* If time exceeded...       */
  1077.      return(-4);                                /* ...exit with error        */
  1078.  
  1079.    return(0);                                   /* all is ok                 */
  1080. }
  1081.  
  1082.  
  1083. /******************************************************************************
  1084.  *
  1085.  * IO_INPUT - Input character
  1086.  *
  1087.  * process      1. Test carrier detect
  1088.  *              2. Return -1 if carrier dropped
  1089.  *              3. Test for no activity
  1090.  *              4. Return -2 if no activity
  1091.  *              5. Return -2 if no activity
  1092.  *              6. Test for time limit exceeded
  1093.  *              7. Return -3 if less than 2 minutes
  1094.  *              8. Return -4 if time limit exceeded
  1095.  *              9. Test for character ready
  1096.  *             10. Goto 1 if no data available
  1097.  *             11. Process local if local ready
  1098.  *             12. Process remote if remote ready
  1099.  *             13. Return character
  1100.  * input        none
  1101.  * output       Returns -1 if carrier dropped
  1102.  *              Returns -2 if no remote activity
  1103.  *              Returns -3 if less than 2 minutes remaining
  1104.  *              Returns -4 if no time remaining
  1105.  *              Returns chararcter
  1106.  *****************************************************************************/
  1107.  
  1108. io_input()
  1109. {
  1110. long    cur_time();                             /* Get current time decl     */
  1111. long    check_time;                             /* Cur time storage          */
  1112. int     stat;                                   /* Input status variable     */
  1113.  
  1114.    mark_time = cur_time();                      /* Flag current time         */
  1115.  
  1116.    while(1)                                     /* Do until we get something */
  1117.    {
  1118.      if(modem_carrier())                        /* If carrier dropped...     */
  1119.        return(-1);                              /* ...exit with error        */
  1120.  
  1121.      check_time = cur_time();                   /* Check current time        */
  1122.      if(check_time < mark_time)                 /* If we wrapped past 12...  */
  1123.        check_time += DAY_SECONDS;               /* ...adjust it              */
  1124.      if(check_time > (mark_time + 180L))        /* If it has been 3 mins...  */
  1125.        return(-2);                              /* ...exit with error        */
  1126.  
  1127.      stat = test_timeout();                     /* Test remote time access   */
  1128.      if(stat == -1)                             /* If time warning msg...    */
  1129.        return(-3);                              /* ...exit with warning      */
  1130.      if(stat == -2)                             /* If time exceeded...       */
  1131.        return(-4);                              /* ...exit with error        */
  1132.  
  1133.      stat = io_status();                        /* Test if char available    */
  1134.      if(stat == 1)                              /* If keyboard char...       */
  1135.        return(local_input());                   /* ...return it              */
  1136.      if(stat == 2)                              /* If remote char...         */
  1137.      {
  1138.        stat = modem_input();                    /* ...return it              */
  1139.        if(stat)
  1140.          return(stat);
  1141.      }
  1142.    }
  1143. }
  1144.  
  1145.  
  1146. /******************************************************************************
  1147.  *
  1148.  * IO_LINPUT - Input line with line feed
  1149.  *
  1150.  * process      1. Read a line
  1151.  *              2. Print a crlf sequence
  1152.  *              3. Return 0
  1153.  * input        Pointer to buffer
  1154.  * output       Returns 0
  1155.  *****************************************************************************/
  1156.  
  1157. io_linput(buffer)
  1158.  
  1159. char    *buffer;                                /* Buffer to store input in  */
  1160. {
  1161.    io_lxinput(buffer);                          /* Read a line               */
  1162.    print_string("\r\n");                        /* Echo a new line           */
  1163.    return(0);                                   /* Exit no error             */
  1164. }
  1165.  
  1166.  
  1167. /******************************************************************************
  1168.  *
  1169.  * IO_LXINPUT - Input line without line feed
  1170.  *
  1171.  * process      1. Read a caharcter
  1172.  *              2. If -1 return ~NO_CARRIER
  1173.  *              3. If -2 return ~NOT_ACTIVE
  1174.  *              4. If -3 return ~TIME_WARNING
  1175.  *              5. If -4 return ~TIMEOUT
  1176.  *              6. If cr then teminate input
  1177.  *              7. If bs then print bs/space/bs
  1178.  *              8. Ignore if buffer if full
  1179.  *              9. Ignore if less than 20H and goto 1
  1180.  *             10. Store character
  1181.  *             11. Echo to output
  1182.  *             12. Goto 1
  1183.  * input        Pointer to buffer
  1184.  * output       Returns 0
  1185.  *****************************************************************************/
  1186.  
  1187. io_lxinput(buffer)
  1188.  
  1189. char    *buffer;                                /* Buffer to store chars in  */
  1190. {
  1191. int     count = 0;                              /* Character counter         */
  1192. int     key;                                    /* Character input variable  */
  1193. int     max = 80;                               /* Max buffer size           */
  1194.  
  1195.   while(1)                                      /* Repeat till done...       */
  1196.   {
  1197.     key = io_input();                           /* Get a character           */
  1198.  
  1199.     if(key == -1)                               /* If carrier dropped...     */
  1200.     {
  1201.       strcpy(buffer, "~NO_CARRIER");            /* ...flag it                */
  1202.       return(0);                                /* ...exit                   */
  1203.     }
  1204.     else if(key == -2)                          /* If input inactive...      */
  1205.     {
  1206.       strcpy(buffer, "~NOT_ACTIVE");            /* ...flag it                */
  1207.       return(0);                                /* ...exit                   */
  1208.     }
  1209.     else if(key == -3)                          /* If time warning...        */
  1210.     {
  1211.       strcpy(buffer, "~TIME_WARNING");          /* ...flag it                */
  1212.       return(0);                                /* ...exit                   */
  1213.     }
  1214.     else if(key == -4)                          /* If timeout...             */
  1215.     {
  1216.       strcpy(buffer, "~TIMEOUT");               /* ...flag it                */
  1217.       return(0);                                /* ...exit                   */
  1218.     }
  1219.     else if(key == 0x0d)                        /* If carriage return...     */
  1220.     {
  1221.       buffer[count] = 0x00;                     /* ...flag end of string     */
  1222.       return(0);                                /* ...exit                   */
  1223.     }
  1224.     else if(key == 0x08)                        /* If backspace...           */
  1225.     {
  1226.       if(count > 0)                             /* ...If buffer not empty... */
  1227.       {
  1228.         count--;                                /* ......adjust count        */
  1229.         print_char(8);                          /* ......backup              */
  1230.       }
  1231.     }
  1232.     else if(key >= 0x20)                        /* If printable character... */
  1233.     {
  1234.       if(count < max)                           /* ...If buffer not ful...   */
  1235.       {
  1236.         buffer[count] = key;                    /* ......store character     */
  1237.         count++;                                /* ......adjust count        */
  1238.         print_char(key);                        /* ......and echo it         */
  1239.       }
  1240.     }
  1241.   }
  1242. }
  1243.  
  1244.  
  1245. /******************************************************************************
  1246.  *
  1247.  * TIO_INPUT - Input character
  1248.  *
  1249.  * process      1. Test carrier detect
  1250.  *              2. Return -1 if carrier dropped
  1251.  *              3. Test for no activity
  1252.  *              4. Return -2 if no activity
  1253.  *              5. Return -2 if no activity
  1254.  *              6. Test for time limit exceeded
  1255.  *              7. Return -3 if less than 2 minutes
  1256.  *              8. Return -4 if time limit exceeded
  1257.  *              9. Test for character ready
  1258.  *             10. Goto 1 if no data available
  1259.  *             11. Process local if local ready
  1260.  *             12. Process remote if remote ready
  1261.  *             13. Return character
  1262.  * input        none
  1263.  * output       Returns -1 if carrier dropped
  1264.  *              Returns -2 if no remote activity
  1265.  *              Returns -3 if less than 2 minutes remaining
  1266.  *              Returns -4 if no time remaining
  1267.  *              Returns chararcter
  1268.  *****************************************************************************/
  1269.  
  1270. tio_input(ticks)
  1271.  
  1272. int     ticks;
  1273. {
  1274. long    cur_time();                             /* Get current time decl     */
  1275. long    check_time;                             /* Cur time storage          */
  1276. int     stat;                                   /* Input status variable     */
  1277.  
  1278.    mark_time = cur_time();                      /* Flag current time         */
  1279.    if(ticks != 0)
  1280.    {
  1281.      mark_time2 = mark_time;
  1282.      tick_time = mark_time + ticks;             /* Flag timeout time         */
  1283.    }
  1284.  
  1285.    while(1)                                     /* Do until we get something */
  1286.    {
  1287.      if(modem_carrier())                        /* If carrier dropped...     */
  1288.        return(-1);                              /* ...exit with error        */
  1289.  
  1290.      check_time = cur_time();                   /* Check current time        */
  1291.      if(check_time < mark_time)                 /* If we wrapped past 12...  */
  1292.        check_time += DAY_SECONDS;               /* ...adjust it              */
  1293.      if(check_time > (mark_time + 180L))        /* If it has been 3 mins...  */
  1294.        return(-2);                              /* ...exit with error        */
  1295.  
  1296.      stat = test_timeout();                     /* Test remote time access   */
  1297.      if(stat == -1)                             /* If time warning msg...    */
  1298.        return(-3);                              /* ...exit with warning      */
  1299.      if(stat == -2)                             /* If time exceeded...       */
  1300.        return(-4);                              /* ...exit with error        */
  1301.  
  1302.      if(check_time < mark_time2)                /* If we wrapped past 12...  */
  1303.        check_time += DAY_SECONDS;               /* ...adjust it              */
  1304.      if(check_time > tick_time)                 /* If timer has expired...   */
  1305.        return(-5);                              /* ...exit with error        */
  1306.  
  1307.      stat = io_status();                        /* Test if char available    */
  1308.      if(stat == 1)                              /* If keyboard char...       */
  1309.        return(local_input());                   /* ...return it              */
  1310.      if(stat == 2)                              /* If remote char...         */
  1311.      {
  1312.        stat = modem_input();                    /* ...return it              */
  1313.        if(stat)
  1314.          return(stat);
  1315.      }
  1316.    }
  1317. }
  1318.  
  1319.  
  1320. /******************************************************************************
  1321.  *
  1322.  * TIO_LINPUT - Timed input line with line feed
  1323.  *
  1324.  * process      1. Read a line
  1325.  *              2. Print a crlf sequence
  1326.  *              3. Return 0
  1327.  * input        Pointer to buffer
  1328.  * output       Returns 0
  1329.  *****************************************************************************/
  1330.  
  1331. tio_linput(buffer, ticks)
  1332.  
  1333. char    *buffer;                                /* Buffer to store input in  */
  1334. int     ticks;                                  /* Time to wait              */
  1335. {
  1336.    tio_lxinput(buffer, ticks);                  /* Read a line               */
  1337.    print_string("\r\n");                        /* Echo a new line           */
  1338.    return(0);                                   /* Exit no error             */
  1339. }
  1340.  
  1341.  
  1342. /******************************************************************************
  1343.  *
  1344.  * TIO_LXINPUT - Input line without line feed
  1345.  *
  1346.  * process      1. Read a character
  1347.  *              2. If -1 return ~NO_CARRIER
  1348.  *              3. If -2 return ~NOT_ACTIVE
  1349.  *              4. If -3 return ~TIME_WARNING
  1350.  *              5. If -4 return ~TIMEOUT
  1351.  *              6. If -5 return ~TIMER
  1352.  *              7. If cr then teminate input
  1353.  *              8. If bs then print bs/space/bs
  1354.  *              9. Ignore if buffer if full
  1355.  *             10. Ignore if less than 20H and goto 1
  1356.  *             11. Store character
  1357.  *             12. Echo to output
  1358.  *             12. Goto 1
  1359.  * input        Pointer to buffer
  1360.  * output       Returns 0
  1361.  *****************************************************************************/
  1362.  
  1363. tio_lxinput(buffer, ticks)
  1364.  
  1365. char    *buffer;                                /* Buffer to store chars in  */
  1366. int     ticks;                                  /* Time to wait              */
  1367. {
  1368. long    cur_time();                             /* Get current time decl     */
  1369. int     count = 0;                              /* Character counter         */
  1370. int     key;                                    /* Character input variable  */
  1371. int     max = 80;                               /* Max buffer size           */
  1372.  
  1373.   mark_time2 = cur_time();                      /* Flag current time         */
  1374.   tick_time = mark_time2 + ticks;               /* Flag timeout time         */
  1375.   while(1)                                      /* Repeat till done...       */
  1376.   {
  1377.     key = tio_input(0);                         /* Get a character           */
  1378.  
  1379.     if(key == -1)                               /* If carrier dropped...     */
  1380.     {
  1381.       strcpy(buffer, "~NO_CARRIER");            /* ...flag it                */
  1382.       return(0);                                /* ...exit                   */
  1383.     }
  1384.     else if(key == -2)                          /* If input inactive...      */
  1385.     {
  1386.       strcpy(buffer, "~NOT_ACTIVE");            /* ...flag it                */
  1387.       return(0);                                /* ...exit                   */
  1388.     }
  1389.     else if(key == -3)                          /* If time warning...        */
  1390.     {
  1391.       strcpy(buffer, "~TIME_WARNING");          /* ...flag it                */
  1392.       return(0);                                /* ...exit                   */
  1393.     }
  1394.     else if(key == -4)                          /* If timeout...             */
  1395.     {
  1396.       strcpy(buffer, "~TIMEOUT");               /* ...flag it                */
  1397.       return(0);                                /* ...exit                   */
  1398.     }
  1399.     else if(key == -5)                          /* If timeout...             */
  1400.     {
  1401.       strcpy(buffer, "~TIMER");                 /* ...flag it                */
  1402.       return(0);                                /* ...exit                   */
  1403.     }
  1404.     else if(key == 0x0d)                        /* If carriage return...     */
  1405.     {
  1406.       buffer[count] = 0x00;                     /* ...flag end of string     */
  1407.       return(0);                                /* ...exit                   */
  1408.     }
  1409.     else if(key == 0x08)                        /* If backspace...           */
  1410.     {
  1411.       if(count > 0)                             /* ...If buffer not empty... */
  1412.       {
  1413.         count--;                                /* ......adjust count        */
  1414.         print_char(8);                          /* ......backup              */
  1415.       }
  1416.     }
  1417.     else if(key >= 0x20)                        /* If printable character... */
  1418.     {
  1419.       if(count < max)                           /* ...If buffer not ful...   */
  1420.       {
  1421.         buffer[count] = key;                    /* ......store character     */
  1422.         count++;                                /* ......adjust count        */
  1423.         print_char(key);                        /* ......and echo it         */
  1424.       }
  1425.     }
  1426.   }
  1427. }
  1428.  
  1429.  
  1430. /******************************************************************************
  1431.  *
  1432.  * IO_LEXINPUT - Input line without line feed or echo
  1433.  *
  1434.  * process      1. Read a caharcter
  1435.  *              2. If -1 return ~NO_CARRIER
  1436.  *              3. If -2 return ~NOT_ACTIVE
  1437.  *              4. If -3 return ~TIME_WARNING
  1438.  *              5. If -4 return ~TIMEOUT
  1439.  *              6. If cr then teminate input
  1440.  *              7. If bs then print bs/space/bs
  1441.  *              8. Ignore if buffer if full
  1442.  *              9. Ignore if less than 20H and goto 1
  1443.  *             10. Store character
  1444.  *             11. Echo to output
  1445.  *             12. Goto 1
  1446.  * input        Pointer to buffer
  1447.  * output       Returns 0
  1448.  *****************************************************************************/
  1449.  
  1450. io_lexinput(buffer)
  1451.  
  1452. char    *buffer;                                /* Buffer to store chars in  */
  1453. {
  1454. int     count = 0;                              /* Character counter         */
  1455. int     key;                                    /* Character input variable  */
  1456. int     max = 80;                               /* Max buffer size           */
  1457.  
  1458.   while(1)                                      /* Repeat till done...       */
  1459.   {
  1460.     key = io_input();                           /* Get a character           */
  1461.  
  1462.     if(key == -1)                               /* If carrier dropped...     */
  1463.     {
  1464.       strcpy(buffer, "~NO_CARRIER");            /* ...flag it                */
  1465.       return(0);                                /* ...exit                   */
  1466.     }
  1467.     else if(key == -2)                          /* If input inactive...      */
  1468.     {
  1469.       strcpy(buffer, "~NOT_ACTIVE");            /* ...flag it                */
  1470.       return(0);                                /* ...exit                   */
  1471.     }
  1472.     else if(key == -3)                          /* If time warning...        */
  1473.     {
  1474.       strcpy(buffer, "~TIME_WARNING");          /* ...flag it                */
  1475.       return(0);                                /* ...exit                   */
  1476.     }
  1477.     else if(key == -4)                          /* If timeout...             */
  1478.     {
  1479.       strcpy(buffer, "~TIMEOUT");               /* ...flag it                */
  1480.       return(0);                                /* ...exit                   */
  1481.     }
  1482.     else if(key == 0x0d)                        /* If carriage return...     */
  1483.     {
  1484.       buffer[count] = 0x00;                     /* ...flag end of string     */
  1485.       return(0);                                /* ...exit                   */
  1486.     }
  1487.     else if(key == 0x08)                        /* If backspace...           */
  1488.     {
  1489.       if(count > 0)                             /* ...If buffer not empty... */
  1490.       {
  1491.         count--;                                /* ......adjust count        */
  1492.       }
  1493.     }
  1494.     else if(key >= 0x20)                        /* If printable character... */
  1495.     {
  1496.       if(count < max)                           /* ...If buffer not ful...   */
  1497.       {
  1498.         buffer[count] = key;                    /* ......store character     */
  1499.         count++;                                /* ......adjust count        */
  1500.       }
  1501.     }
  1502.   }
  1503. }
  1504.  
  1505.  
  1506. /******************************************************************************
  1507.  *
  1508.  * IO_PAUSE - Print an erasable prompt & wait for ENTER
  1509.  *
  1510.  * process      1. Print the message
  1511.  *              2. Wait for enter
  1512.  *              3. If -1 exit
  1513.  *              4. If -2 exit
  1514.  *              5. If -3 exit
  1515.  *              6. If -4 exit
  1516.  *              7. If no cr then goto 2
  1517.  *              8. If remote is printing device exit
  1518.  *              9. Erase message
  1519.  *             10. Exit no errors
  1520.  * input        Pointer to message
  1521.  *              Centering flag (0 = left margin, 1 = center)
  1522.  * output       Returns 0
  1523.  *****************************************************************************/
  1524.  
  1525. io_pause(message, center)
  1526.  
  1527. char    *message;                               /* Message to print          */
  1528. int     center;                                 /* Centering flag            */
  1529. {
  1530. int     count = 0;                              /* Character counter         */
  1531. int     key;                                    /* Character input variable  */
  1532. int     i;                                      /* Work variable             */
  1533.  
  1534.    /*
  1535.     * Print the message
  1536.     */
  1537.  
  1538.    if(center)                                   /* If centering...           */
  1539.      count = (80 - strlen(message)) / 2;        /* ...calc amount to indent  */
  1540.  
  1541.    for(i = 0 ; i < count ; i++)                 /* Indent desired amount     */
  1542.      print_char(' ');
  1543.  
  1544.  
  1545.    /*
  1546.     * Wait for ENTER
  1547.     */
  1548.  
  1549.    while(1)                                     /* Repeat till done...       */
  1550.    {
  1551.      key = io_input();                          /* Get a character           */
  1552.  
  1553.      if(key == -1)                              /* If carrier dropped...     */
  1554.        return(0);                               /* ...exit                   */
  1555.      else if(key == -2)                         /* If input inactive...      */
  1556.        return(0);                               /* ...exit                   */
  1557.      else if(key == -3)                         /* If time warning...        */
  1558.        return(0);                               /* ...exit                   */
  1559.      else if(key == -4)                         /* If timeout...             */
  1560.        return(0);                               /* ...exit                   */
  1561.  
  1562.      else if(key == 0x0d)                       /* If carriage return...     */
  1563.      {
  1564.        if(user_nulls)                           /* If printing terminal...   */
  1565.        {
  1566.          print_char('\r');                      /* ...kick out a line        */
  1567.          print_char('\n');
  1568.        }
  1569.        else                                     /* Otherwise...              */
  1570.          backup(count + strlen(message));       /* ...erase the message      */
  1571.  
  1572.        return(0);                               /* ...exit                   */
  1573.      }
  1574.    }
  1575. }
  1576.  
  1577.  
  1578. /******************************************************************************
  1579.  *
  1580.  * EOL_DISPLAY - Erase to End of Line
  1581.  *
  1582.  * process      1. If ANSI graphics then send sequence
  1583.  *              2. Return 0
  1584.  * input        none
  1585.  * output       Returns 0
  1586.  *****************************************************************************/
  1587.  
  1588. eol_display()
  1589. {
  1590. int     i;
  1591.  
  1592.   if(user_graphics == 2)                        /* If ANSI graphics...       */
  1593.   {
  1594.     for(i = 0 ; i < strlen(eol) ; i++)          /* ...print cls sequence     */
  1595.       print_char(eol[i]);
  1596.   }
  1597.   return(0);                                    /* All done, no errors       */
  1598. }
  1599.  
  1600.  
  1601. /******************************************************************************
  1602.  *
  1603.  * CLS_DISPLAY - Clear the display
  1604.  *
  1605.  * process      1. If ANSI graphics then send sequence
  1606.  *              2. Else print line feeds
  1607.  *              3. Return 0
  1608.  * input        none
  1609.  * output       Returns 0
  1610.  *****************************************************************************/
  1611.  
  1612. cls_display()
  1613. {
  1614. int     i;
  1615.  
  1616.   if(user_graphics == 2)                        /* If ANSI graphics...       */
  1617.   {
  1618.     for(i = 0 ; i < strlen(cls) ; i++)          /* ...print cls sequence     */
  1619.       print_char(cls[i]);
  1620.  
  1621.     local_line_no = 0;                          /* Reset line number         */
  1622.     put_local_banner();                         /* Rewrite banner message    */
  1623.     set_local_cursor(0,0);                      /* Guarantee good position   */
  1624.   }
  1625.   else                                          /* Else use line feeds       */
  1626.   {
  1627.     print_char('\r');
  1628.     for(i = 0 ; i < 25 ; i++)                   /* Do 25 lines               */
  1629.     {
  1630.       print_char('\n');
  1631.     }
  1632.   }
  1633.   return(0);                                    /* All done, no errors       */
  1634. }
  1635.  
  1636.  
  1637. /******************************************************************************
  1638.  *
  1639.  * CLS2_DISPLAY - Clear the display
  1640.  *
  1641.  * process      1. If ANSI graphics then send sequence
  1642.  *              2. Else print line feeds
  1643.  *              3. Return 0
  1644.  * input        none
  1645.  * output       Returns 0
  1646.  *****************************************************************************/
  1647.  
  1648. cls2_display()
  1649. {
  1650. int     i;
  1651.  
  1652.   if(user_graphics == 2)                        /* If ANSI graphics...       */
  1653.   {
  1654.     for(i = 0 ; i < strlen(cls) ; i++)          /* ...print cls sequence     */
  1655.       print_char(cls[i]);
  1656.  
  1657.     local_line_no = 0;                          /* Reset line number         */
  1658.     put_local_banner();                         /* Rewrite banner message    */
  1659.     set_local_cursor(0,0);                      /* Guarantee good position   */
  1660.   }
  1661.   else                                          /* Else use line feeds       */
  1662.   {
  1663.     print_char('\r');
  1664.     for(i = 0 ; i < 3 ; i++)                    /* Do 3 lines                */
  1665.     {
  1666.       print_char('\n');
  1667.     }
  1668.   }
  1669.   return(0);                                    /* All done, no errors       */
  1670. }
  1671.  
  1672.  
  1673. /******************************************************************************
  1674.  *
  1675.  * NO_CURSOR - Turn off local cursor
  1676.  *
  1677.  * process      1. Set cursor size via BIOS
  1678.  *              2. Return 0
  1679.  * input        none
  1680.  * output       none
  1681.  *****************************************************************************/
  1682.  
  1683. no_cursor()
  1684. {
  1685. union   REGS inregs, outregs;                   /* Bios access structure     */
  1686. struct  SREGS   segregs;
  1687.  
  1688.   inregs.x.ax = (0x100);                        /* Bios function number      */
  1689.   inregs.h.ch = 32;                             /* Cursor start line         */
  1690.   inregs.h.cl = 32;                             /* Cursor end line           */
  1691.   int86x(0x10, &inregs, &outregs, &segregs);    /* Do it                     */
  1692.   return(0);                                    /* Exit no errors            */
  1693. }
  1694.  
  1695.  
  1696. /******************************************************************************
  1697.  *
  1698.  * SMALL_CURSOR - Set a small local cursor
  1699.  *
  1700.  * process      1. Set cursor size via BIOS
  1701.  *              2. Return 0
  1702.  * input        none
  1703.  * output       none
  1704.  *****************************************************************************/
  1705.  
  1706. small_cursor()
  1707. {
  1708. union   REGS inregs, outregs;                   /* Bios access structure     */
  1709. struct  SREGS   segregs;
  1710.  
  1711.   inregs.x.ax = (0x100);                        /* Bios function number      */
  1712.   inregs.h.ch = 6;                              /* Cursor start line         */
  1713.   inregs.h.cl = 7;                              /* Cursor end line           */
  1714.   int86x(0x10, &inregs, &outregs, &segregs);    /* Do it                     */
  1715.   return(0);                                    /* Exit no errors            */
  1716. }
  1717.  
  1718.  
  1719. /******************************************************************************
  1720.  *
  1721.  * MEDIUM_CURSOR - Set a medium local cursor
  1722.  *
  1723.  * process      1. Set cursor size via BIOS
  1724.  *              2. Return 0
  1725.  * input        none
  1726.  * output       none
  1727.  *****************************************************************************/
  1728.  
  1729. medium_cursor()
  1730. {
  1731. union   REGS inregs, outregs;                   /* Bios access structure     */
  1732. struct  SREGS   segregs;
  1733.  
  1734.   inregs.x.ax = (0x100);                        /* Bios function number      */
  1735.   inregs.h.ch = 3;                              /* Cursor start line         */
  1736.   inregs.h.cl = 7;                              /* Cursor end line           */
  1737.   int86x(0x10, &inregs, &outregs, &segregs);    /* Do it                     */
  1738.   return(0);                                    /* Exit no errors            */
  1739. }
  1740.  
  1741.  
  1742. /******************************************************************************
  1743.  *
  1744.  * LARGE_CURSOR - Set a large local cursor
  1745.  *
  1746.  * process      1. Set cursor size via BIOS
  1747.  *              2. Return 0
  1748.  * input        none
  1749.  * output       none
  1750.  *****************************************************************************/
  1751.  
  1752. large_cursor()
  1753. {
  1754. union   REGS inregs, outregs;                   /* Bios access structure     */
  1755. struct  SREGS   segregs;
  1756.  
  1757.   inregs.x.ax = (0x100);                        /* Bios function number      */
  1758.   inregs.h.ch = 0;                              /* Cursor start line         */
  1759.   inregs.h.cl = 7;                              /* Cursor end line           */
  1760.   int86x(0x10, &inregs, &outregs, &segregs);    /* Do it                     */
  1761.   return(0);                                    /* Exit no errors            */
  1762. }
  1763.  
  1764.  
  1765. /*
  1766.  *
  1767.  * Position the Cursor
  1768.  *
  1769.  */
  1770.  
  1771. position_cursor(x, y)
  1772.  
  1773. int     x, y;
  1774. {
  1775.    if(user_graphics == 2)                       /* Only support if ANSI      */
  1776.    {
  1777.      print_string("\033[%d;%dH", y + 1, x + 1);
  1778.  
  1779.      local_line_no = y;
  1780.      return(0);
  1781.    }
  1782.    return(1);                                   /* All done, no errors       */
  1783. }
  1784.  
  1785.  
  1786. /*
  1787.  *
  1788.  * Print a Character
  1789.  *
  1790.  */
  1791.  
  1792. print_char(data)
  1793.  
  1794. int     data;                                   /* Character to print        */
  1795. {
  1796.    print_charx(data);                           /* Print it                  */
  1797.    if(data == 8)                                /* If it is a backspace...   */
  1798.    {
  1799.      print_charx(' ');                          /* ...make it destructive    */
  1800.      print_charx(8);
  1801.    }
  1802.    return(0);                                   /* No errors                 */
  1803. }
  1804.  
  1805.  
  1806. /*
  1807.  *
  1808.  * Print a Character
  1809.  *
  1810.  */
  1811.  
  1812. print_charx(data)
  1813.  
  1814. int     data;                                   /* Character to print        */
  1815. {
  1816. union   REGS inregs, outregs;
  1817. int     i, j;
  1818.  
  1819.    if(user_caps && (data >= 'a') && (data <= 'z')) /* Adjust if case sensative */
  1820.      j = data & 0x5f;
  1821.    else
  1822.      j = data;
  1823.  
  1824.    local_output(j);                             /* Send to local console     */
  1825.    if(remote_user)                              /* If remote active...       */
  1826.      modem_output(j);                           /* ...he gets it too         */
  1827.  
  1828.    return(0);                                   /* No errors                 */
  1829. }
  1830.  
  1831.  
  1832. /*
  1833.  *
  1834.  * Backup
  1835.  *
  1836.  */
  1837.  
  1838. backup(count)
  1839.  
  1840. int     count;                                  /* Characters to backup      */
  1841. {
  1842. int     i;
  1843.  
  1844.    for(i = 0 ; i < count ; i++)
  1845.      print_char(8);
  1846.  
  1847.    return(0);                                   /* No errors                 */
  1848. }
  1849.  
  1850.  
  1851. /*
  1852.  *
  1853.  * Print a String
  1854.  *
  1855.  */
  1856.  
  1857. print_string(string)
  1858.  
  1859. char    *string;                                /* String to print           */
  1860. {
  1861. va_list vlist;
  1862. int     i;
  1863.  
  1864.   va_start(vlist, string);
  1865.   vsprintf(dmoutbuff, string, vlist);
  1866.   va_end(vlist);
  1867.  
  1868.   for(i = 0 ; i < strlen(dmoutbuff) ; i++)
  1869.     print_char(dmoutbuff[i]);
  1870.  
  1871.   return(0);
  1872. }
  1873.  
  1874.  
  1875. /*
  1876.  *
  1877.  * Metered Line Output
  1878.  *
  1879.  */
  1880.  
  1881. print_metered(line, string, iobuff)
  1882.  
  1883. int     *line;                                  /* Pointer to line count     */
  1884. char    *string;                                /* Pointer to message        */
  1885. char    *iobuff;                                /* Pointer to buffer         */
  1886. {
  1887.    print_string(string);                        /* Print the message         */
  1888.    (*line)++;                                   /* Bump line counter         */
  1889.    if(*line > (user_page - 2))                  /* If at end of page...      */
  1890.    {
  1891.      print_string("                             Continue [Y], N, NS...");
  1892.      io_lxinput(iobuff);                        /* ...wait for response      */
  1893.      backup(strlen(iobuff) + 52);
  1894.      *line = 0;                                 /* ...reset line count       */
  1895.      if(strcmp(strupr(iobuff), "\0") == 0)      /* ...if continue...         */
  1896.        return(0);                               /* ......exit continue       */
  1897.      if(strcmp(strupr(iobuff), "Y") == 0)       /* ...if continue...         */
  1898.        return(0);                               /* ......exit continue       */
  1899.      if(strcmp(strupr(iobuff), "NS") == 0)      /* ...if continuous...       */
  1900.        return(1);                               /* ......exit continuous     */
  1901.      if(strcmp(strupr(iobuff), "N") == 0)       /* ...if stop...             */
  1902.        return(2);                               /* ......exit stop           */
  1903.      else                                       /* ...otherwise...           */
  1904.        return(-1);                              /* ......exit uncertain      */
  1905.    }
  1906.    return(0);                                   /* Exit continue             */
  1907. }
  1908.  
  1909.  
  1910. /*
  1911.  *
  1912.  * Metered Line Output
  1913.  * (no abort)
  1914.  *
  1915.  */
  1916.  
  1917. print_meteredx(line, string, iobuff)
  1918.  
  1919. int     *line;                                  /* Pointer to line count     */
  1920. char    *string;                                /* Pointer to message        */
  1921. char    *iobuff;                                /* Pointer to buffer         */
  1922. {
  1923.    print_string(string);                        /* Print the message         */
  1924.    (*line)++;                                   /* Bump line counter         */
  1925.    if(*line > (user_page - 2))                  /* If at end of page...      */
  1926.    {
  1927.      print_string("                           Press [ENTER] to continue...");
  1928.      io_lxinput(iobuff);                        /* ...wait for response      */
  1929.      backup(strlen(iobuff) + 55);
  1930.      *line = 0;                                 /* ...reset line count       */
  1931.      if(strcmp(strupr(iobuff), "\0") == 0)      /* ...if continue...         */
  1932.        return(0);                               /* ......exit continue       */
  1933.      else                                       /* ...otherwise...           */
  1934.        return(-1);                              /* ......exit uncertain      */
  1935.    }
  1936.    return(0);                                   /* Exit continue             */
  1937. }
  1938.  
  1939.  
  1940. /******************************************************************************
  1941.  *
  1942.  * IO_WAIT - Wait for output to complete
  1943.  *
  1944.  * process      1. If local, exit
  1945.  *              2. Wait for TX buffer empty
  1946.  *              3. Exit
  1947.  * input        None
  1948.  * output       Returns AX = -1 if no carrier
  1949.  *              Returns AX = 0 if TX buffer empty
  1950.  *              Returns AX = 1 if timeout
  1951.  *****************************************************************************/
  1952.  
  1953. io_wait()
  1954. {
  1955.    /*
  1956.     * Wait for complete
  1957.     */
  1958.  
  1959.     local_wait();                              /* Wait for complete          */
  1960.     return(modem_wait());                      /* Wait for complete          */
  1961. }
  1962.  
  1963.  
  1964. /******************************************************************************
  1965.  *
  1966.  * IO_IFLUSH - Purge all input
  1967.  *
  1968.  * process      1. Clear the buffers
  1969.  *              2. Exit
  1970.  * input        None
  1971.  * output       Returns AX = 0
  1972.  *****************************************************************************/
  1973.  
  1974. io_iflush()
  1975. {
  1976.    /*
  1977.     * Flush buffers if in use
  1978.     */
  1979.  
  1980.     local_iflush();                             /* Flush local input         */
  1981.     modem_iflush();                             /* Flush remote input        */
  1982.  
  1983.     return(0);                                  /* Always returns 0          */
  1984. }
  1985.  
  1986.  
  1987. /******************************************************************************
  1988.  *
  1989.  * IO_OFLUSH - Purge all output
  1990.  *
  1991.  * process      1. Clear the buffers
  1992.  *              2. Exit
  1993.  * input        None
  1994.  * output       Returns AX = 0
  1995.  *****************************************************************************/
  1996.  
  1997. io_oflush()
  1998. {
  1999.    /*
  2000.     * Flush buffers
  2001.     */
  2002.  
  2003.     local_oflush();                             /* Flush local output        */
  2004.     modem_oflush();                             /* Flush remote output       */
  2005.  
  2006.     return(0);                                  /* Always returns 0          */
  2007. }
  2008.  
  2009.  
  2010. /* ************************************************************************* */
  2011. /* ************************   SUPPORT FUNCTIONS   ************************** */
  2012. /* ************************************************************************* */
  2013.  
  2014.  
  2015. /* ********************* */
  2016. /*    Read Port Info.    */
  2017. /* ********************* */
  2018.  
  2019. dmread_ports()
  2020. {
  2021. char    *fgets();                       /* Get string function               */
  2022.  
  2023. FS      cfg;                            /* Config file structure             */
  2024. char    parms[7][41];                   /* Config parameters                 */
  2025. int     not_done;                       /* Loop control                      */
  2026. int     commid;                         /* Comm Port ID being defined        */
  2027. int     portid;                         /* Comm Port address                 */
  2028. int     irqid;                          /* IRQ number                        */
  2029. int     intid;                          /* Interrupt flag                    */
  2030. int     handid;                         /* Handshake flag                    */
  2031. int     passid;                         /* Passthrough flag                  */
  2032. int     levels;                         /* Levels defined                    */
  2033. int     i, j, k;                        /* Work variables                    */
  2034.  
  2035.  
  2036.   /*
  2037.    * Open up the config file
  2038.    */
  2039.  
  2040.    strcpy(cfg.name, bbs_dir);                   /* Build filename            */
  2041.    strcat(cfg.name, "PORTS.BBS");               /* Open node file            */
  2042.    i = file_open(&cfg, FREAD, FTEXT, FNOCREATE); /* Open node file           */
  2043.    if(i)                                        /* If file not there...      */
  2044.      return(0);                                 /* ...then use defaults      */
  2045.  
  2046.  
  2047.   /*
  2048.    * Process the file
  2049.    */
  2050.  
  2051.    not_done = 1;
  2052.    levels   = 0;
  2053.    while(not_done)
  2054.    {
  2055.     /*
  2056.      * Read in the record
  2057.      */
  2058.  
  2059.      if(fgets(dminbuff, 128, cfg.fd) == 0L)
  2060.        not_done = 0;
  2061.      else if(dminbuff[0] == 0x1a)
  2062.        not_done = 0;
  2063.      else if(dminbuff[0] != ';')
  2064.      {
  2065.        i = 0;
  2066.        k = 0;
  2067.        while((k < 7) &&
  2068.              (dminbuff[i] != 0x0d) && (dminbuff[i] != 0x0a) &&
  2069.              (dminbuff[i] != 0x00) && (dminbuff[i] != 0x1a))
  2070.        {
  2071.          while((dminbuff[i] == ' ') || (dminbuff[i] == 0x09))
  2072.            i++;
  2073.  
  2074.          j = 0;
  2075.          while((dminbuff[i] != ' ') && (dminbuff[i] != 0x09) &&
  2076.                (dminbuff[i] != 0x0d) && (dminbuff[i] != 0x0a) &&
  2077.                (dminbuff[i] != 0x00) && (dminbuff[i] != 0x1a))
  2078.          {
  2079.            parms[k][j] = dminbuff[i];
  2080.            j++;
  2081.            i++;
  2082.          }
  2083.          parms[k][j] = '\0';
  2084.          k++;
  2085.        }
  2086.  
  2087.  
  2088.        if(k == 0)
  2089.        {
  2090.          /* Ignore blank lines */
  2091.        }
  2092.        else if(parms[0][0] == ';')
  2093.        {
  2094.          /* Skip comment line */
  2095.        }
  2096.        else if((k == 6) || ((k == 7) && (parms[6][0] == ';')))
  2097.        {
  2098.          commid = get_commid(parms[0]);
  2099.          if((commid < 1) || (commid > 8))
  2100.          {
  2101.            file_close(&cfg);
  2102.            return(-3);                  /* Bad comm port parameter           */
  2103.          }
  2104.  
  2105.          portid = get_portid(parms[1]);
  2106.          if(portid == -1)
  2107.          {
  2108.            file_close(&cfg);
  2109.            return(-4);                  /* Bad comm port address             */
  2110.          }
  2111.  
  2112.          irqid = get_irqid(parms[2]);
  2113.          if(irqid == -1)
  2114.          {
  2115.            file_close(&cfg);
  2116.            return(-5);                  /* Bad IRQ number                    */
  2117.          }
  2118.  
  2119.          intid = get_intid(parms[3]);
  2120.          if(intid == -1)
  2121.          {
  2122.            file_close(&cfg);
  2123.            return(-6);                  /* Bad interrupt enable flag         */
  2124.          }
  2125.  
  2126.          handid = get_handid(parms[4]);
  2127.          if(handid == -1)
  2128.          {
  2129.            file_close(&cfg);
  2130.            return(-7);                  /* Bad handshaking flag              */
  2131.          }
  2132.  
  2133.          passid = get_yesno(parms[5]);
  2134.          if(passid == -1)
  2135.          {
  2136.            file_close(&cfg);
  2137.            return(-8);                  /* Bad passthrough flag              */
  2138.          }
  2139.  
  2140.          if(dmio_ports[commid - 1].defined == 2)
  2141.          {
  2142.            file_close(&cfg);
  2143.            return(-9);                  /* Duplicate port definition         */
  2144.          }
  2145.          else                           /* else store the definitions        */
  2146.          {
  2147.            dmio_ports[commid - 1].defined    = 2;
  2148.            dmio_ports[commid - 1].address    = portid;
  2149.            dmio_ports[commid - 1].irq_id     = irqid;
  2150.            dmio_ports[commid - 1].int_enable = intid;
  2151.            dmio_ports[commid - 1].handshake  = handid;
  2152.            dmio_ports[commid - 1].passthru   = passid;
  2153.            levels++;
  2154.          }
  2155.        }
  2156.        else
  2157.        {
  2158.          file_close(&cfg);
  2159.          return(-2);                    /* Illegal number of parameters      */
  2160.        }
  2161.      }
  2162.    }
  2163.    file_close(&cfg);
  2164.  
  2165.    if(levels)
  2166.      return(0);                         /* config file read ok               */
  2167.    else
  2168.      return(-10);                       /* No defined comm ports in file     */
  2169. }
  2170.  
  2171.  
  2172. /* ********************* */
  2173. /*    Convert Comm ID    */
  2174. /* ********************* */
  2175.  
  2176. get_commid(string)
  2177.  
  2178. char    *string;
  2179. {
  2180. int     value;                          /* return value                      */
  2181. int     i;                              /* string index                      */
  2182.  
  2183.    /*
  2184.     * Make sure it is COMx
  2185.     */
  2186.  
  2187.    if(strlen(string) != 4)              /* Must be 4 chars long              */
  2188.      return(0);
  2189.  
  2190.    if(strnicmp(string, "COM", 3) != 0)  /* Must be in COMx format            */
  2191.      return(0);
  2192.  
  2193.  
  2194.    /*
  2195.     * Get port ID and range check it
  2196.     */
  2197.  
  2198.    value = atoi(&string[3]);            /* Get port id                       */
  2199.  
  2200.    if((value < 1) || (value > 8))       /* Range check it                    */
  2201.      return(0);
  2202.    else
  2203.      return(value);
  2204. }
  2205.  
  2206.  
  2207. /* ********************* */
  2208. /*   Convert Comm Addr   */
  2209. /* ********************* */
  2210.  
  2211. get_portid(string)
  2212.  
  2213. char    *string;
  2214. {
  2215. int     value;                          /* return value                      */
  2216. int     i;                              /* string index                      */
  2217.  
  2218.  
  2219.    /*
  2220.     * Parse out & validate port number
  2221.     */
  2222.  
  2223.    if(strlen(string) > 4)               /* Must be 4 chars long or less      */
  2224.      return(-1);
  2225.  
  2226.  
  2227.    /*
  2228.     * Get port address
  2229.     */
  2230.  
  2231.    value = 0;                           /* Init the value                    */
  2232.    for(i = 0 ; i < strlen(string) ; i++)
  2233.    {
  2234.      switch(string[i])
  2235.      {
  2236.        case '0':        /* Digit value 0 */
  2237.                         value *= 16;
  2238.                         value += 0;
  2239.                         break;
  2240.        case '1':        /* Digit value 1 */
  2241.                         value *= 16;
  2242.                         value += 1;
  2243.                         break;
  2244.        case '2':        /* Digit value 2 */
  2245.                         value *= 16;
  2246.                         value += 2;
  2247.                         break;
  2248.        case '3':        /* Digit value 3 */
  2249.                         value *= 16;
  2250.                         value += 3;
  2251.                         break;
  2252.        case '4':        /* Digit value 4 */
  2253.                         value *= 16;
  2254.                         value += 4;
  2255.                         break;
  2256.        case '5':        /* Digit value 5 */
  2257.                         value *= 16;
  2258.                         value += 5;
  2259.                         break;
  2260.        case '6':        /* Digit value 6 */
  2261.                         value *= 16;
  2262.                         value += 6;
  2263.                         break;
  2264.        case '7':        /* Digit value 7 */
  2265.                         value *= 16;
  2266.                         value += 7;
  2267.                         break;
  2268.        case '8':        /* Digit value 8 */
  2269.                         value *= 16;
  2270.                         value += 8;
  2271.                         break;
  2272.        case '9':        /* Digit value 9 */
  2273.                         value *= 16;
  2274.                         value += 9;
  2275.                         break;
  2276.        case 'a':        /* Digit value A */
  2277.        case 'A':
  2278.                         value *= 16;
  2279.                         value += 10;
  2280.                         break;
  2281.        case 'b':        /* Digit value B */
  2282.        case 'B':
  2283.                         value *= 16;
  2284.                         value += 11;
  2285.                         break;
  2286.        case 'c':        /* Digit value C */
  2287.        case 'C':
  2288.                         value *= 16;
  2289.                         value += 12;
  2290.                         break;
  2291.        case 'd':        /* Digit value D */
  2292.        case 'D':
  2293.                         value *= 16;
  2294.                         value += 13;
  2295.                         break;
  2296.        case 'e':        /* Digit value E */
  2297.        case 'E':
  2298.                         value *= 16;
  2299.                         value += 14;
  2300.                         break;
  2301.        case 'f':        /* Digit value F */
  2302.        case 'F':
  2303.                         value *= 16;
  2304.                         value += 15;
  2305.                         break;
  2306.        default:         /* Bad digit */
  2307.                         return(-1);
  2308.      }
  2309.    }
  2310.    return(value);
  2311. }
  2312.  
  2313.  
  2314. /* ********************* */
  2315. /*    Convert IRQ ID     */
  2316. /* ********************* */
  2317.  
  2318. get_irqid(string)
  2319.  
  2320. char    *string;
  2321. {
  2322. int     value;                          /* return value                      */
  2323. int     i;                              /* string index                      */
  2324.  
  2325.    /*
  2326.     * Make sure it is IRQx
  2327.     */
  2328.  
  2329.    if(strlen(string) != 4)              /* Must be 4 chars long              */
  2330.      return(-1);
  2331.  
  2332.    if(strnicmp(string, "IRQ", 3) != 0)  /* Must be in IRQx format            */
  2333.      return(-1);
  2334.  
  2335.  
  2336.    /*
  2337.     * Get port ID and range check it
  2338.     */
  2339.  
  2340.    value = atoi(&string[3]);            /* Get IRQ number                    */
  2341.  
  2342.    if((value < 0) || (value > 7))       /* Range check it                    */
  2343.      return(-1);
  2344.    else
  2345.      return(value);
  2346. }
  2347.  
  2348.  
  2349. /* ********************* */
  2350. /*    Convert YES/NO     */
  2351. /* ********************* */
  2352.  
  2353. get_yesno(string)
  2354.  
  2355. char    *string;
  2356. {
  2357. int     value;                          /* return value                      */
  2358. int     i;                              /* string index                      */
  2359.  
  2360.  
  2361.    /*
  2362.     * Get YES/NO answer
  2363.     */
  2364.  
  2365.    if(strcmpi(string, "YES") == 0)      /* Test for YES parameter            */
  2366.      return(1);
  2367.    else if(strcmpi(string, "NO") == 0)  /* Test for NO parameter             */
  2368.      return(0);
  2369.    else                                 /* otherwise is bad                  */
  2370.      return(-1);
  2371. }
  2372.  
  2373.  
  2374. /* ********************* */
  2375. /*  Convert Access Type  */
  2376. /* ********************* */
  2377.  
  2378. get_intid(string)
  2379.  
  2380. char    *string;
  2381. {
  2382. int     value;                          /* return value                      */
  2383. int     i;                              /* string index                      */
  2384.  
  2385.  
  2386.    /*
  2387.     * Get access parameter
  2388.     */
  2389.  
  2390.    if(strcmpi(string, "BIOS") == 0)     /* Test for BIOS/Fossil access       */
  2391.      return(0);
  2392.    else if(strcmpi(string, "PORT") == 0)/* Test for Direct port access       */
  2393.      return(1);
  2394.    else if(strcmpi(string, "INTR") == 0)/* Test for Interrupt driven access  */
  2395.      return(2);
  2396.    else                                 /* otherwise is bad                  */
  2397.      return(-1);
  2398. }
  2399.  
  2400.  
  2401. /* ********************* */
  2402. /*   Convert Handshake   */
  2403. /* ********************* */
  2404.  
  2405. get_handid(string)
  2406.  
  2407. char    *string;
  2408. {
  2409. int     value;                          /* return value                      */
  2410. int     i;                              /* string index                      */
  2411.  
  2412.  
  2413.    /*
  2414.     * Get handshake parameter
  2415.     */
  2416.  
  2417.    if(strcmpi(string, "NONE") == 0)     /* Test for NONE parameter           */
  2418.      return(0);
  2419.    else if(strcmpi(string, "SOFT") == 0)/* Test for SOFT parameter           */
  2420.      return(1);
  2421.    else if(strcmpi(string, "HARD") == 0)/* Test for HARD parameter           */
  2422.      return(2);
  2423.    else if(strcmpi(string, "BOTH") == 0)/* Test for BOTH parameter           */
  2424.      return(3);
  2425.    else                                 /* otherwise is bad                  */
  2426.      return(-1);
  2427. }
  2428.  
  2429.  
  2430.